package logic

import (
	"common"
	"common/zapx"
	"errors"
	"go.uber.org/zap"
	"gorm.io/gen/field"
	"gorm.io/gorm"
	"models/dal/model"
	"models/dal/query"
	"time"
	"user/internal/pb"
)

// Register 注册用户
func Register(email, password, nickName string, avatar *string) error {
	return query.Q.Transaction(func(tx *query.Query) error {
		//检查用户是否存在
		ctx, cancel := common.WithTimeoutContext(time.Second * 2)
		defer cancel()
		userModel := tx.FaUser
		cnt, err := userModel.WithContext(ctx).Where(userModel.Email.Eq(email)).Count()
		if err != nil {
			return err
		}
		if cnt > 0 {
			return errors.New("用户已存在")
		}
		//密码
		salt := common.RandomStr(30)
		p, err := common.EncryptionPassword(password, salt)
		if err != nil {
			return err
		}
		//注册
		if avatar == nil {
			a := "avatar/default.png"
			avatar = &a
		}
		return userModel.WithContext(ctx).Create(&model.FaUser{
			Email:    email,
			Nickname: nickName,
			Avatar:   *avatar,
			Password: p,
			Salt:     salt,
		})
	})
}

// Login 登录
func Login(email, password string) (*pb.UserLoginResponse, error) {
	userModel := query.Q.FaUser
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	user, err := userModel.WithContext(ctx).Where(userModel.Email.Eq(email)).First()
	if err != nil {
		zapx.Logger.Error("查询用户失败", zap.Error(err))
		return nil, errors.New("系统错误,查询失败")
	}
	//判断密码是否正确
	p, err := common.EncryptionPassword(password, user.Salt)
	if err != nil {
		zapx.Logger.Error("加密用户密码失败", zap.Error(err))
		return nil, errors.New("系统错误,加密失败")
	}
	if p != user.Password {
		return nil, errors.New("密码不正确")
	}
	//生成 token
	token, err := common.GenerateJwtToken(user.ID)
	if err != nil {
		zapx.Logger.Error("生成用户jwt令牌失败", zap.Error(err))
		return nil, errors.New("系统错误,生成令牌失败")
	}
	return &pb.UserLoginResponse{
		Token: token,
		User: &pb.UserEntity{
			NickName: user.Nickname,
			Avatar:   user.Avatar,
		},
	}, nil
}

func EditProfile(userId int32, nickName *string, avatar *string) error {
	userModel := query.Q.FaUser
	ctx, cancel := common.WithTimeoutContext(time.Second * 2)
	defer cancel()
	//查询用户
	raw, err := userModel.WithContext(ctx).Where(userModel.ID.Eq(userId)).First()
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("用户不存在")
		}
		zapx.Logger.Error("[EditProfile]查询用户失败", zap.Error(err))
		return errors.New("系统错误")
	}
	var update []field.AssignExpr
	if nickName != nil {
		update = append(update, userModel.Nickname.Value(*nickName))
	}
	if avatar != nil {
		update = append(update, userModel.Avatar.Value(*avatar))
	}
	if len(update) > 0 {
		_, err := userModel.WithContext(ctx).Where(userModel.ID.Eq(raw.ID)).UpdateSimple(update...)
		if err != nil {
			zapx.Logger.Error("[EditProfile]更新用户失败", zap.Error(err))
			return errors.New("系统错误")
		}
	}
	return nil
}
